package mtt.control;

import java.util.Stack;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;

import mtt.model.calendar.Day;
import mtt.model.calendar.Event;
import mtt.model.calendar.Week;
import mtt.model.record.MttCalendarRecordStore;
import mtt.view.IMttDisplayAble;
import mtt.view.MainMenuView;
import mtt.view.calendar.EventView;
import mtt.view.calendar.DayView;
import mtt.view.calendar.WeekView;

/**
 * Der DisplayController dient zur Navigation durch den MTT . Er enthält für
 * jeden Ablauf eine Methode die nacheinander alle "Seiten" anzeigt
 * 
 * @author hyphen
 */
public class DisplayController implements CommandListener {

	/**
	 * einzige Instanz des DisplayControllers
	 */
	private static final DisplayController displayController = new DisplayController();

	/**
	 * in diesem Stack werden alle bisher aufgerufenen Displayables abgelegt,
	 * wird in einem DisplayAble der "zurück"-Button gedrückt wird das
	 * DisplayAble aus dem Stack entfernt und das vorhergehende Angezeigt.
	 * 
	 * Der Stack enhält IMttDisplayAble-Objekte
	 */
	private static final Stack stackDisplayAbles = new Stack();

	/**
	 * Factory-Methode den DisplayController, liefert immer das gleiche
	 * DisplayController-Objekt. Es wird somit die Singleton-Eigenschaft
	 * erzwungen.
	 * 
	 * @return DisplayController
	 */
	public static final DisplayController getInstance() {
		return DisplayController.displayController;
	}

	/**
	 * enthält das aktuell angezeigt DisplayAble
	 */
	private IMttDisplayAble currentDisplayAble;

	/**
	 * Display instanz des MIDlets
	 * 
	 * @uml.property name="display"
	 */
	private Display display;

	/**
	 * To get an instance of DisplayController use the Factory-Method
	 * DisplayController.getInstance()
	 */
	private DisplayController() {
	}

	/**
	 * Fängt alle Commands ab und leitet sie an das entsprechende DisplayAble
	 * weiter
	 */
	public void commandAction(Command command, Displayable displayable) {

		if (command.getCommandType() == Command.EXIT) {
			/*
			 * Programm beenden
			 */
			ApplicationController.getInstance().applicationShutdown();

		} else if (command.getCommandType() == Command.BACK) {
			/*
			 * vorheriges DisplayAble anzeigen
			 */
			goBack();
		} else if (displayable == currentDisplayAble.getDisplayable()) {
			/*
			 * Command an DisplayAble weiterleiten
			 */
			this.currentDisplayAble.commandAction(command);
		}
	}

	/**
	 * @return
	 * @uml.property name="display"
	 */
	public final Display getDisplay() {
		return display;
	}

	/**
	 * zeigt das vorherige DisplayAble an
	 */
	public void goBack() {

		/*
		 * aktuelles DisplayAble löschen, damit es nicht wieder zum Stack
		 * hinzugefügt wird
		 */
		this.currentDisplayAble = null;

		if (stackDisplayAbles.size() == 0) {
			/*
			 * Hauptmenü anzeigen wenn der Stack keine Elemente mehr enthält
			 */
			showMainMenu();
		} else {
			/*
			 * letztes DisplayAble aus dem Stack holen
			 */
			setCurrentDisplayAble((IMttDisplayAble) stackDisplayAbles.pop());
		}

	}

	/**
	 * lädt die weekEvents der übergebenen Woche
	 * 
	 * @param week
	 */
	private void loadWeekEvents(Week week) {
		/*
		 * Termine der Woche laden
		 */
		try {
			MttCalendarRecordStore mttCalendarRecordStore;
			mttCalendarRecordStore = MttCalendarRecordStore.getInstance();
			mttCalendarRecordStore.loadWeekEvents(week);
		} catch (RecordStoreFullException e) {
			// TODO mtt.view.error Fehler-DisplayAble anzeigen
			e.printStackTrace();
		} catch (RecordStoreNotFoundException e) {
			// TODO mtt.view.error Fehler-DisplayAble anzeigen
			e.printStackTrace();
		} catch (RecordStoreException e) {
			// TODO mtt.view.error Fehler-DisplayAble anzeigen
			e.printStackTrace();
		}
	}

	/**
	 * @param displayable
	 * @uml.property name="currentDisplayAble"
	 */
	private void setCurrentDisplayAble(IMttDisplayAble displayable) {

		/*
		 * aktuelles DisplayAble in des Stack schieben
		 */
		if (this.currentDisplayAble != null) {
			stackDisplayAbles.push(this.currentDisplayAble);
		}

		/*
		 * neues DisplayAble setzen
		 */
		this.currentDisplayAble = displayable;

		/*
		 * DisplayAble anzeigen
		 */
		this.display.setCurrent(displayable.getDisplayable());
	}

	/**
	 * @param display
	 * @uml.property name="display"
	 */
	public final void setDisplay(Display display) {
		this.display = display;
	}

	/**
	 * gibt den Übergebenen Alert aus und wartet auf OK
	 */
	public void showAlertError(String alertText, Image alertImage) {
		Alert alert = new Alert("Error", alertText, alertImage, AlertType.ERROR);

		display.setCurrent(alert, currentDisplayAble.getDisplayable());
	}

	/**
	 * Zeigt die Termindetails des Termins mit der ID Day.ID_* an
	 * 
	 * @param Day.ID_*
	 */
	public void showEvent(Event event) {
		/*
		 * EventView mit ausgewähltem Event anzeigen
		 */
		EventView view = EventView.getInstance(event);
		setCurrentDisplayAble(view);
	}

	/**
	 * zeigt den übergebenen Tag an
	 * 
	 * @param Day
	 */
	public void showDayView(Day day) {
		DayView view = DayView.getInstance();
		view.initDayView(day);
		setCurrentDisplayAble(view);
	}

	public void showInfoView() {
		// TODO Auto-generated method stub

	}

	/**
	 * zeigt das zu letzt dargestellt DisplayAble bzw das Hauptmenü an
	 */
	public void showLastView() {
		if (currentDisplayAble == null) {
			showMainMenu();
		} else {
			Alert alert = new Alert("Pause beendet", "weiter gehts ...", null,
					AlertType.INFO);
			display.setCurrent(alert, currentDisplayAble.getDisplayable());
		}
	}

	public void showMainMenu() {
		MainMenuView mainMenuView = MainMenuView.getInstance();
		setCurrentDisplayAble(mainMenuView);
	}

	public void showMarkView() {
		// TODO Auto-generated method stub

	}

	public void showOptionView() {
		// TODO Auto-generated method stub

	}

	/**
	 * zeigt die aktuelle Woche an
	 */
	public void showWeekViewCurrent() {

		/*
		 * aktuelle Woche holen
		 */
		CalendarController calendarController = CalendarController
				.getInstance();
		Week week = calendarController.getCurrentWeek();

		/*
		 * Termine der Woche laden
		 */
		loadWeekEvents(week);

		/*
		 * WeekView erstellen und mit den Wochendaten initialisieren
		 */
		WeekView view = WeekView.getInstace();
		view.setWeek(week);

		/*
		 * WeekView anzeigen
		 */
		setCurrentDisplayAble(view);
	}

	/**
	 * zeigt den Stundenplan der nächsten Woche an
	 */
	public void showWeekViewNext() {

	}

	/**
	 * zeigt den Stundenplan der vorherigen Woche an
	 */
	public void showWeekViewPrev() {

	}
}
